package dou.net;

import java.util.Hashtable;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 创建和管理线程池对象
 * @author wizardc
 */
public class ThreadPoolManager
{
    private static ThreadPoolManager _instance;

    /**
     * 获取该类全局唯一的实例
     * @return 该类全局唯一的实例
     */
    public static synchronized ThreadPoolManager getInstance()
    {
        if(_instance == null)
        {
            _instance = new ThreadPoolManager();
        }
        return _instance;
    }

    private Hashtable<String, ThreadPoolExecutor> _pool;

    /**
     * 构造函数
     */
    private ThreadPoolManager()
    {
        _pool = new Hashtable<String, ThreadPoolExecutor>();
    }

    /**
     * 创建或获取一个线程池对象，如果该线程池对象未创建过则效果同下面的代码 getServiceHandlerPool(name, 2, 5, 5L, Thread.NORM_PRIORITY)
     * @param name 该线程池对象的名称
     * @return 对应名称的线程池对象
     */
    public ThreadPoolExecutor getServiceHandlerPool(String name)
    {
        return getServiceHandlerPool(name, 2, 5, 5L, Thread.NORM_PRIORITY);
    }

    /**
     * 创建或获取一个线程池对象，如果该线程池对象已经创建过则后 3 个参数无效
     * @param name 该线程池对象的名称
     * @param coreSize 核心线程大小
     * @param maxSize 最大线程大小，超过该大小后加入的线程会被阻塞并等待资源
     * @param keepTime 空闲线程的保持时间，单位为秒
     * @param priority 线程的优先级
     * @return 对应名称的线程池对象
     */
    public ThreadPoolExecutor getServiceHandlerPool(String name, int coreSize, int maxSize, long keepTime, int priority)
    {
        if(_pool.containsKey(name))
        {
            return _pool.get(name);
        }
        // 由于使用 LinkedBlockingQueue 对象，等待的阻塞线程为无限，最后的拒绝处理对象可省去，基本上不会拒绝任何的处理
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(coreSize, maxSize, keepTime, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new PriorityThreadFactory(name, priority));
        _pool.put(name, threadPool);
        return threadPool;
    }

    /**
     * 为线程池对象提供线程创建的工厂类，支持线程优先级设置
     */
    private class PriorityThreadFactory implements ThreadFactory
    {
        // 记录该工厂类的名称
        private String _name;
        // 记录该工厂类的优先级
        private int _priority;
        // 记录该工厂类创建的线程当前的序号
        private AtomicInteger _threadNumber;
        // 该工厂类创建的线程的线程组对象
        private ThreadGroup _threadGroup;

        /**
         * 创建一个 PriorityThreadFactory 对象
         * @param name 由该工厂创建的线程的名称
         * @param priority 由该工厂创建的线程的优先级
         */
        public PriorityThreadFactory(String name, int priority)
        {
            _name = name;
            _priority = priority;
            _threadNumber = new AtomicInteger(0);
            _threadGroup = new ThreadGroup(_name);
        }

        @Override
        public Thread newThread(Runnable runnable)
        {
            Thread thread = new Thread(_threadGroup, runnable);
            thread.setName(_name + "-" + _threadNumber.incrementAndGet());
            thread.setPriority(_priority);
            return thread;
        }
    }
}
